package com.stock.api.util;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.stock.api.basic.BusinessException;
import com.stock.api.domain.stock.StockCodeBean;
import com.stock.api.domain.stock.StockHistoryBean;
import com.stock.api.dto.stock.StockInfo;
import com.stock.api.dto.stock.StockModel;
import com.stock.comm.util.DateUtil;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;

import java.io.*;
import java.math.BigDecimal;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 股票工具类
 * Created by zhangfeng on 15/9/8.
 */
public class StockUtils {

    private static Logger log = Logger.getLogger(StockUtils.class);
    public static final String DEF_CHATSET = "UTF-8";
    public static final int DEF_CONN_TIMEOUT = 30000;
    public static final int DEF_READ_TIMEOUT = 30000;
    public static String userAgent = "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.66 Safari/537.36";

    //配置您申请的聚合Api KEY
    public static final String APPKEY = "77eca40d93ad5883a5974606761e4e73";

    //百度Api
    private static String httpUrl = "http://apis.baidu.com/apistore/stockservice/stock";
    //聚合Api
    private static String httpJuHeUrl = "http://web.juhe.cn:8080/finance/stock/hs";
    //股票实时价格
    private static Map<String, BigDecimal> stockPriceMap = new HashMap<>();

    private static boolean flag = true;
    //我买的股票涨跌幅
    private static Map<String, BigDecimal> changeRateMap = new HashMap<>();


    /**
     * 获取股票收盘数据
     *
     * @param stockCode :参数
     * @return 返回结果
     */
    public static String request(String stockCode) throws Exception {
        BufferedReader reader = null;
        String result = null;
        StringBuffer sbf = new StringBuffer();
        String apiUrl = httpUrl + "?stockid=" + stockCode + "&list=1";
        try {
            URL url = new URL(apiUrl);
            HttpURLConnection connection = (HttpURLConnection) url
                    .openConnection();
            connection.setRequestMethod("GET");
            // 填入apikey到HTTP header   http://apistore.baidu.com/apiworks/servicedetail/115.html
            connection.setRequestProperty("apikey", "083cbf503c1504c41301b5e8f778d40d");
            connection.connect();
            InputStream is = connection.getInputStream();
            reader = new BufferedReader(new InputStreamReader(is, "UTF-8"));
            String strRead = null;
            while ((strRead = reader.readLine()) != null) {
                sbf.append(strRead);
                sbf.append("\r\n");
            }
            reader.close();
            result = decodeUnicode(sbf.toString());
        } catch (Exception e) {
            throw new Exception(e.getMessage());
        }
        return result;
    }

    /**
     * 获取股票收盘数据 聚合api
     *
     * @param stockCode
     * @return
     */
    public static String requestJuHe(String stockCode) {
        String result = null;
        Map params = new HashMap();//请求参数
        params.put("gid", stockCode);//股票编号，上海股市以sh开头，深圳股市以sz开头如：sh601009
        params.put("key", "77eca40d93ad5883a5974606761e4e73");//APP Key

        try {
            result = net(httpJuHeUrl, params, "GET");
            JSONObject object = JSONObject.parseObject(result);
//            if (object.getIntValue("error_code") == 0) {
//                System.out.println(object.get("result"));
//            } else {
//                System.out.println(object.get("error_code") + ":" + object.get("reason"));
//            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    /**
     * 将map型转为请求参数型
     *
     * @param data
     * @return
     */
    public static String urlencode(Map<String, Object> data) throws UnsupportedEncodingException {
        StringBuilder sb = new StringBuilder();
        if (data != null && !data.isEmpty()) {
            for (Map.Entry i : data.entrySet()) {
                sb.append(i.getKey()).append("=").append(URLEncoder.encode(i.getValue() + "", "UTF-8")).append("&");
            }
        }
        return sb.toString();
    }


    /**
     * 根据股票代码获取当天收盘数据
     *
     * @param stockCodeList
     * @return
     */
    public static List<StockHistoryBean> getStockHistoryData(List<StockCodeBean> stockCodeList) throws Exception {
        List<StockHistoryBean> historyBeanList = new ArrayList<>();
        StringBuffer strBuffer = new StringBuffer();
        for (int i = 0; i < stockCodeList.size(); i++) {
            StockCodeBean stockCodeBean = stockCodeList.get(i);
            if (strBuffer == null || strBuffer.length() == 0)
                strBuffer.append(stockCodeBean.getStockType() + stockCodeBean.getStockCode());
            else
                strBuffer.append("," + stockCodeBean.getStockType() + stockCodeBean.getStockCode());

            if ((i != 0 && i % 200 == 0) || i == stockCodeList.size() - 1) {
                /**数据抓取*/
                String jsonResult = requestJuHe(strBuffer.toString());
                try {
                    /**数据转换*/
                    transformJuHeStockHistory(historyBeanList, jsonResult);
                } catch (Exception e) {
                    jsonResult = request(strBuffer.toString());
                    /**使用备用接口*/
                    transformStockHistory(historyBeanList, JSON.parseObject(jsonResult, StockModel.class));
                }
                strBuffer.delete(0, strBuffer.length());
                stockPriceMap.put(historyBeanList.get(i).getStockCode(), historyBeanList.get(i).getClosePrice());
            }
        }
        return historyBeanList;
    }

    /**
     * 转换聚合数据
     *
     * @param historyBeanList
     * @param jsonResult
     */
    public static void transformJuHeStockHistory(List<StockHistoryBean> historyBeanList, String jsonResult) {
        JSONObject object = JSONObject.parseObject(jsonResult);
        if (object.getIntValue("error_code") == 0) {
            object = JSONObject.parseObject(jsonResult).getJSONArray("result").getJSONObject(0).getJSONObject("dapandata");
            StockHistoryBean stockHistoryBean = new StockHistoryBean();
            /**今日收盘价*/
            stockHistoryBean.setClosePrice(object.getBigDecimal("dot"));
            /**涨跌幅*/
            stockHistoryBean.setChangeRate(object.getBigDecimal("rate"));
            /**涨跌额*/
            stockHistoryBean.setUpsandDowns(object.getBigDecimal("nowPic"));
            /**状态*/
            stockHistoryBean.setStatus("00");
            historyBeanList.add(stockHistoryBean);
        } else {
            throw new BusinessException("股票数据抓取失败");
        }
    }

    /***
     * 数据转换
     *
     * @param historyBeanList
     * @param stockModel
     */
    public static void transformStockHistory(List<StockHistoryBean> historyBeanList, StockModel stockModel) throws ParseException {

        StockInfo[] stockInfos = stockModel.getRetData().getStockinfo();
        if (stockInfos != null && stockInfos.length > 0) {
            for (StockInfo stockInfo : stockInfos) {
                if (StringUtils.isNotEmpty(stockInfo.getName())) {
                    StockHistoryBean stockHistoryBean = new StockHistoryBean();
                    /**股票代码*/
                    stockHistoryBean.setStockCode(stockInfo.getCode().substring(2, stockInfo.getCode().length()));
                    /**收盘日期*/
                    stockHistoryBean.setStockDate(DateUtil.formatCurrentDate());
                    /**昨日收盘*/
                    stockHistoryBean.setYesterdayClosePrice(stockInfo.getClosingPrice());
                    /**今日开盘*/
                    stockHistoryBean.setOpenPrice(stockInfo.getOpenningPrice());
                    /**涨跌额*/
                    stockHistoryBean.setUpsandDowns(stockInfo.getCurrentPrice().subtract(stockInfo.getClosingPrice()));
                    /**涨跌幅 = (今日收盘价 - 昨日收盘价) / 昨日收盘价 */
                    if (stockInfo.getCurrentPrice().intValue() == 0) {
                        /**今日收盘*/
                        stockHistoryBean.setClosePrice(stockInfo.getClosingPrice());
                        /**涨跌幅*/
                        stockHistoryBean.setChangeRate(new BigDecimal(0));
                        /**涨跌额*/
                        stockHistoryBean.setUpsandDowns(new BigDecimal(0));
                    } else {
                        /**今日收盘*/
                        stockHistoryBean.setClosePrice(stockInfo.getCurrentPrice());
                        /**涨跌幅*/
                        stockHistoryBean.setChangeRate(stockInfo.getCurrentPrice().subtract(stockInfo.getClosingPrice()).divide(stockInfo.getClosingPrice(), 4, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_HALF_UP));
                        /**涨跌额*/
                        stockHistoryBean.setUpsandDowns(stockInfo.getCurrentPrice().subtract(stockInfo.getClosingPrice()));
                    }
                    /**今日最高*/
                    stockHistoryBean.setHighestAmount(stockInfo.gethPrice());
                    /**今日最低价*/
                    stockHistoryBean.setLowestAmnout(stockInfo.getlPrice());
                    /**成交量*/
                    stockHistoryBean.setStockVolume(new BigDecimal(0));
                    /**总成交额*/
                    stockHistoryBean.setTotalTurnover(new BigDecimal(0));
                    /**换手率*/
                    stockHistoryBean.setTurnoverRate(new BigDecimal(0));
                    /**状态*/
                    stockHistoryBean.setStatus("00");
                    historyBeanList.add(stockHistoryBean);
                }
            }
        }
    }


    /***
     * unicode转换中文
     *
     * @param theString
     * @return
     */
    public static String decodeUnicode(String theString) {

        char aChar;
        int len = theString.length();
        StringBuffer outBuffer = new StringBuffer(len);
        for (int x = 0; x < len; ) {
            aChar = theString.charAt(x++);
            if (aChar == '\\') {
                aChar = theString.charAt(x++);
                if (aChar == 'u') {
                    // Read the xxxx
                    int value = 0;
                    for (int i = 0; i < 4; i++) {
                        aChar = theString.charAt(x++);
                        switch (aChar) {
                            case '0':
                            case '1':
                            case '2':
                            case '3':
                            case '4':
                            case '5':
                            case '6':
                            case '7':
                            case '8':
                            case '9':
                                value = (value << 4) + aChar - '0';
                                break;
                            case 'a':
                            case 'b':
                            case 'c':
                            case 'd':
                            case 'e':
                            case 'f':
                                value = (value << 4) + 10 + aChar - 'a';
                                break;
                            case 'A':
                            case 'B':
                            case 'C':
                            case 'D':
                            case 'E':
                            case 'F':
                                value = (value << 4) + 10 + aChar - 'A';
                                break;
                            default:
                                throw new IllegalArgumentException(
                                        "Malformed   \\uxxxx   encoding.");
                        }

                    }
                    outBuffer.append((char) value);
                } else {
                    if (aChar == 't')
                        aChar = '\t';
                    else if (aChar == 'r')
                        aChar = '\r';
                    else if (aChar == 'n')
                        aChar = '\n';
                    else if (aChar == 'f')
                        aChar = '\f';
                    outBuffer.append(aChar);
                }
            } else
                outBuffer.append(aChar);
        }
        return outBuffer.toString();
    }

    /**
     * @param strUrl 请求地址
     * @param params 请求参数
     * @param method 请求方法
     * @return 网络请求字符串
     * @throws Exception
     */
    public static String net(String strUrl, Map params, String method) throws Exception {
        HttpURLConnection conn = null;
        BufferedReader reader = null;
        String rs = null;
        StringBuffer sb = new StringBuffer();
        if (method == null || method.equals("GET")) {
            strUrl = strUrl + "?" + urlencode(params);
        }
        URL url = new URL(strUrl);
        conn = (HttpURLConnection) url.openConnection();
        if (method == null || method.equals("GET")) {
            conn.setRequestMethod("GET");
        } else {
            conn.setRequestMethod("POST");
            conn.setDoOutput(true);
        }
        conn.setRequestProperty("User-agent", userAgent);
        conn.setUseCaches(false);
        conn.setConnectTimeout(DEF_CONN_TIMEOUT);
        conn.setReadTimeout(DEF_READ_TIMEOUT);
        conn.setInstanceFollowRedirects(false);
        conn.connect();
        if (params != null && method.equals("POST")) {
            DataOutputStream out = new DataOutputStream(conn.getOutputStream());
            out.writeBytes(urlencode(params));
        }
        InputStream is = conn.getInputStream();
        reader = new BufferedReader(new InputStreamReader(is, DEF_CHATSET));
        String strRead = null;
        while ((strRead = reader.readLine()) != null) {
            sb.append(strRead);
        }
        return sb.toString();
    }

    /**
     * 根据股票代码获取收盘价
     *
     * @param stockCode
     * @return
     */
    public static BigDecimal getStockPrice(String stockCode) {
        return stockPriceMap.get(stockCode);
    }

    /**
     * 股票实时价格map
     *
     * @return
     */
    public static Map<String, BigDecimal> getStockPriceMap() {
        return stockPriceMap;
    }

    /**
     * 判断是否可以进行数据分析
     *
     * @return
     */
    public synchronized static boolean isFlag() {
        return flag;
    }

    /**
     * 跟新数据分析标志
     *
     * @param flag
     */
    public synchronized static void setFlag(boolean flag) {
        StockUtils.flag = flag;
    }

    /**
     * 获取我的股票涨跌幅Map
     *
     * @return
     */
    public static Map<String, BigDecimal> getChangeRateMap() {
        return changeRateMap;
    }

    /***
     * 获取网页源码
     *
     * @param urlPath
     * @return
     */
    public static String getHtmlContent(String urlPath) {
        try {
            URL url = new URL(urlPath);
            URLConnection urlConnection = url.openConnection();
            BufferedReader br = new BufferedReader(new InputStreamReader(urlConnection.getInputStream(), "UTF-8"));
            String str = "";
            StringBuffer content = new StringBuffer();
            while ((str = br.readLine()) != null) {
                content.append(str);
            }
            br.close();
            return content.toString();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public static void main(String[] args) {
        try {
//            net("http://www.baidu.com",null,"GET");
////            String jsonResult = request("sz002230");
//            String jsonResult = requestJuHe("sh600415");
//            System.out.println(jsonResult);
//            System.out.println(JSONObject.parseObject(jsonResult).getJSONArray("result").getJSONObject(0).get("dapandata"));
//            System.out.println(JSON.toJSONString(JSON.parseObject(jsonResult, StockModel.class)));
//
//
//            Map<String, String> map = new HashMap<>();
//            map.put("aa", "bb");
//            String str = "{\"aa\":\"bb\"}";
//            StockCodeBean stockCodeBean = new StockCodeBean();
//            stockCodeBean.setStockCode("123");
//            System.out.println(JSON.toJSONString(stockCodeBean));
//            JSON.parse(str);

            System.out.println(getHtmlContent("https://service.htsc.com.cn/service/login.jsp"));
        } catch (Exception e) {
            e.printStackTrace();
        }

    }


}
